{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <h1 style=\"font-family: Trebuchet MS; padding: 20px; font-size: 25px; color: #2D2926; text-align: center; line-height: 0.75;background-color: #FF781F\"><b>Unsupervised Learning : Fund Allocation For Countries in Need</b><br></h1>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<center>\n",
    "    <img src=\"http://help-international.org/sites/default/files/images/CAM21488.jpg\" alt=\"Unsupervised Learning\" width=\"40%\">\n",
    "</center>\n",
    "\n",
    "### Problem Statement :\n",
    "\n",
    "HELP International is an international humanitarian NGO that is committed to fighting poverty and providing the people of backward countries with basic amenities and relief during the time of disasters and natural calamities. HELP International have been able to raise around $ 10 million. This money now needs to be allocated strategically and effectively. Hence, inorder to decide the selection of the countries that are in the direst need of aid, data driven decisions are to be made. Thus, it becomes necessary to categorise the countries using socio-economic and health factors that determine the overall development of the country. Thus, based on these clusters of the countries depending on their conditions, funds will be allocated for assistance during the time of disasters and natural calamities. It is a clear cut case of unsupervised learning where we have to create clusters of the countries based on the different feature present.\n",
    "\n",
    "### Aim :\n",
    "- To cluster countries based on numerical features.\n",
    "- It is an **Unsupervised Learning** problem statement.\n",
    "\n",
    "### <center>Dataset Attributes</center>\n",
    "    \n",
    "- **country** : Name of the country\n",
    "- **child_mort** : Death of children under 5 years of age per 1000 live births\n",
    "- **exports** : Exports of goods and services per capita. Given as %age of the GDP per capita\n",
    "- **health** : Total health spending per capita. Given as %age of GDP per capita\n",
    "- **imports** : Imports of goods and services per capita. Given as %age of the GDP per capita\n",
    "- **Income** : Net income per person\n",
    "- **Inflation** : The measurement of the annual growth rate of the Total GDP\n",
    "- **life_expec** : The average number of years a new born child would live if the current mortality patterns are to rem...\n",
    "- **total_fer** : The number of children that would be born to each woman if the current age-fertility rates remain th...\n",
    "- **gdpp** : The GDP per capita. Calculated as the Total GDP divided by the total population."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Notebook Contents :\n",
    "- Dataset Information\n",
    "- Exploratory Data Analysis (EDA)\n",
    "- Summary of EDA\n",
    "- Feature Engineering\n",
    "- Modeling\n",
    "- Conclusion\n",
    "\n",
    "### What you will learn :\n",
    "- Data Visualization techniques. \n",
    "- Feature Engineering & PCA.\n",
    "- K-Means Clustering vs DBSCAN Clustering vs Hierarchical Clustering model performance.\n",
    "\n",
    "### Related Work :\n",
    "\n",
    "- [Binary Classification](https://www.kaggle.com/competitions/titanic/discussion/352223) **: It is a discussion post that describes the approach required to deal with Binary Classification problems explained through notebooks that contain work done on datasets with easy and understandable code explanation!**\n",
    "- [Time Series Analysis](https://www.kaggle.com/competitions/store-sales-time-series-forecasting/discussion/352205) **: It is a discussion post that describes the basics of Time Series Analysis explained through notebooks that contain work done on datasets with easy and understandable code explanation!**\n",
    "- [Unsupervised Learning](https://www.kaggle.com/code/tanmay111999/mall-customer-segmentation-k-means-eda) **: It is a notebook that describes the work on Unsupervised Learning problem using K-Means clustering algorithm!**\n",
    "\n",
    "### Lets get started!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Dataset Information</div></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import the Necessary Libraries :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:27.723629Z",
     "iopub.status.busy": "2022-10-21T12:52:27.722283Z",
     "iopub.status.idle": "2022-10-21T12:52:53.944623Z",
     "shell.execute_reply": "2022-10-21T12:52:53.943015Z",
     "shell.execute_reply.started": "2022-10-21T12:52:27.723512Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import seaborn as sns\n",
    "pd.options.display.float_format = '{:.2f}'.format\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.metrics import silhouette_score\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "\n",
    "import plotly.express as px\n",
    "!pip install -U kaleido\n",
    "import kaleido"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:53.948256Z",
     "iopub.status.busy": "2022-10-21T12:52:53.947457Z",
     "iopub.status.idle": "2022-10-21T12:52:53.992290Z",
     "shell.execute_reply": "2022-10-21T12:52:53.990905Z",
     "shell.execute_reply.started": "2022-10-21T12:52:53.948211Z"
    },
    "scrolled": true,
    "trusted": true
   },
   "outputs": [],
   "source": [
    "data = pd.read_csv('../input/unsupervised-learning-on-country-data/Country-data.csv')\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data Info :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:53.994971Z",
     "iopub.status.busy": "2022-10-21T12:52:53.994464Z",
     "iopub.status.idle": "2022-10-21T12:52:54.007092Z",
     "shell.execute_reply": "2022-10-21T12:52:54.005697Z",
     "shell.execute_reply.started": "2022-10-21T12:52:53.994924Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:54.011929Z",
     "iopub.status.busy": "2022-10-21T12:52:54.011363Z",
     "iopub.status.idle": "2022-10-21T12:52:54.021980Z",
     "shell.execute_reply": "2022-10-21T12:52:54.020440Z",
     "shell.execute_reply.started": "2022-10-21T12:52:54.011884Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "data.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:54.024755Z",
     "iopub.status.busy": "2022-10-21T12:52:54.024255Z",
     "iopub.status.idle": "2022-10-21T12:52:54.058692Z",
     "shell.execute_reply": "2022-10-21T12:52:54.057404Z",
     "shell.execute_reply.started": "2022-10-21T12:52:54.024709Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:54.060569Z",
     "iopub.status.busy": "2022-10-21T12:52:54.060186Z",
     "iopub.status.idle": "2022-10-21T12:52:54.451801Z",
     "shell.execute_reply": "2022-10-21T12:52:54.450674Z",
     "shell.execute_reply.started": "2022-10-21T12:52:54.060533Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "sns.heatmap(data.isnull(),cmap = 'magma',cbar = False);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **No null values** present in the data!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:54.454609Z",
     "iopub.status.busy": "2022-10-21T12:52:54.453758Z",
     "iopub.status.idle": "2022-10-21T12:52:54.498246Z",
     "shell.execute_reply": "2022-10-21T12:52:54.496780Z",
     "shell.execute_reply.started": "2022-10-21T12:52:54.454535Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "data.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:54.500097Z",
     "iopub.status.busy": "2022-10-21T12:52:54.499759Z",
     "iopub.status.idle": "2022-10-21T12:52:54.703137Z",
     "shell.execute_reply": "2022-10-21T12:52:54.702019Z",
     "shell.execute_reply.started": "2022-10-21T12:52:54.500067Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig,ax = plt.subplots(nrows = 1,ncols = 1,figsize = (5,5))\n",
    "\n",
    "colors = ['#FF781F','#2D2926']\n",
    "plt.subplot(1,1,1)\n",
    "sns.heatmap(data.describe().T[['mean']],cmap = 'Oranges',annot = True,fmt = '.2f',linecolor = 'black',linewidths = 0.4,cbar = False);\n",
    "plt.title('Mean Values');\n",
    "\n",
    "fig.tight_layout(pad = 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Exploratory Data Analysis</div></center>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:54.705380Z",
     "iopub.status.busy": "2022-10-21T12:52:54.704963Z",
     "iopub.status.idle": "2022-10-21T12:52:54.716345Z",
     "shell.execute_reply": "2022-10-21T12:52:54.713679Z",
     "shell.execute_reply.started": "2022-10-21T12:52:54.705338Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "col = list(data.columns)\n",
    "col.remove('country')\n",
    "categorical_features = ['country']\n",
    "numerical_features = [*col]\n",
    "print('Categorical Features :',*categorical_features)\n",
    "print('Numerical Features :',*numerical_features)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- For this dataset, as the number of features are less, we manually check the dataset.\n",
    "- Clearly, except **country**, all the features are numerical features with their element datatype being either float or integer.\n",
    "- We use the typical approach for division of features i.e based on the datatypes of the elements of the respective feature.\n",
    "\n",
    "**Eg :** datatype = integer, feature = numerical feature ; datatype = string, feature = categorical feature"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Distribution of Features :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:52:58.332898Z",
     "iopub.status.busy": "2022-10-21T12:52:58.332109Z",
     "iopub.status.idle": "2022-10-21T12:53:00.292654Z",
     "shell.execute_reply": "2022-10-21T12:53:00.291719Z",
     "shell.execute_reply.started": "2022-10-21T12:52:58.332847Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 3,ncols = 3,figsize = (15,15))\n",
    "for i in range(len(numerical_features)):\n",
    "    plt.subplot(3,3,i+1)\n",
    "    sns.distplot(data[numerical_features[i]],color = colors[0])\n",
    "    title = 'Distribution : ' + numerical_features[i]\n",
    "    plt.title(title)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:00.295728Z",
     "iopub.status.busy": "2022-10-21T12:53:00.294331Z",
     "iopub.status.idle": "2022-10-21T12:53:00.304990Z",
     "shell.execute_reply": "2022-10-21T12:53:00.303680Z",
     "shell.execute_reply.started": "2022-10-21T12:53:00.295659Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "len(data['country'].unique()) == len(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **life_expec** displays a **left or negatively skewed data distribution**.\n",
    "- **health** displays a **normally distrubuted data**.\n",
    "- All the remaining features show a **right or positively skewed data distribution**.\n",
    "- Data distribution of **country** is not put out as it has text data and it has the same number of unique values as the length of the dataframe."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Features of Economically Backward Countries :\n",
    "\n",
    "- The country's **per capita income is very low**.\n",
    "- **High Population** that leads to non - availability of resources.\n",
    "- **Unemployment** due to less resources.\n",
    "- **Low country wealth** that leads to **low capital**.\n",
    "- **Inequitable** distribution of **wealth** and **income**.  \n",
    "- **Lack of proper educational amenities** and thus **illiteracy prevails**.\n",
    "- **Low level of living**.\n",
    "- **No technical advancement**.\n",
    "- **Poor health services** coupled with **high birth & death rates**.\n",
    "\n",
    "**HELP Foundation needs to target the countries that display the above characteristics. We will now visualize the data and find the countries that lie at the extremes and the center of the each feature to point out the countries that require assistance!**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### country vs Numerical Features : "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **child_mort : Economically backward nations have a high infant mortality rate!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:03.284499Z",
     "iopub.status.busy": "2022-10-21T12:53:03.283367Z",
     "iopub.status.idle": "2022-10-21T12:53:03.884042Z",
     "shell.execute_reply": "2022-10-21T12:53:03.882928Z",
     "shell.execute_reply.started": "2022-10-21T12:53:03.284458Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'child_mort', data = data.sort_values(ascending = False,by = 'child_mort').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Children Mortalitiy')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'child_mort', data = data.sort_values(ascending = False,by = 'child_mort').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Children Mortalitiy')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'child_mort', data = data.sort_values(ascending = False,by = 'child_mort').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Children Mortalitiy')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **Haiti** has the highest children's deaths. **African countries** have significant positions in this statistic.\n",
    "- At the other extreme of **child_mort**, countries from **Asia and Europe** has some solid presence. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **exports : It is a very important factor for building the nation's economy. Higher the exports of a nation, stronger the nation's economy and more is the wealth generated by the nation!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:05.300025Z",
     "iopub.status.busy": "2022-10-21T12:53:05.299595Z",
     "iopub.status.idle": "2022-10-21T12:53:05.912538Z",
     "shell.execute_reply": "2022-10-21T12:53:05.910177Z",
     "shell.execute_reply.started": "2022-10-21T12:53:05.299991Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'exports', data = data.sort_values(ascending = False,by = 'exports').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Exports (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'exports', data = data.sort_values(ascending = False,by = 'exports').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Exports (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'exports', data = data.sort_values(ascending = False,by = 'exports').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Exports (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **exports** of a nation are usually goods and services created domestically but sold to other nations. Goods and services exported depends on factors like the geographical location, natural resources, population size & their preference towards specific skills, etc.\n",
    "- Despite **Singapore's** population size not being in the top 100, they have the highest number of **exports**. **Luxembourg** & **Malta** have probably followed the same route.\n",
    "- **Afghanistan** & **Nepal** are present in the lower end of **exports**. Geographical locations of these nations have a heavy influence. Countries with lower exports also have small geographical area."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **health : Citizens of the developed nations have higher income and thus they don't have a problem on spending more on healthy lifestyle!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:06.844128Z",
     "iopub.status.busy": "2022-10-21T12:53:06.843643Z",
     "iopub.status.idle": "2022-10-21T12:53:07.425865Z",
     "shell.execute_reply": "2022-10-21T12:53:07.424472Z",
     "shell.execute_reply.started": "2022-10-21T12:53:06.844090Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'health', data = data.sort_values(ascending = False,by = 'health').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Health Spending (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'health', data = data.sort_values(ascending = False,by = 'health').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Health Spending (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'health', data = data.sort_values(ascending = False,by = 'health').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Health Spending (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **US** stands at the top when it comes to spending on health with **17%** of the individual GDP contribution.\n",
    "- **6%** seems to be the mean values of the citizens spending on their **health**.\n",
    "- **Asian** countries dominate the lower end of **health** with less than **3%**. They are the most ignorant citizens when it comes to health."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **imports : It is another attribute that determines the reliance of the nations on other nations for the goods and services!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:08.906847Z",
     "iopub.status.busy": "2022-10-21T12:53:08.906364Z",
     "iopub.status.idle": "2022-10-21T12:53:09.436137Z",
     "shell.execute_reply": "2022-10-21T12:53:09.434825Z",
     "shell.execute_reply.started": "2022-10-21T12:53:08.906811Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'imports', data = data.sort_values(ascending = False,by = 'imports').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Imports (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'imports', data = data.sort_values(ascending = False,by = 'imports').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Imports (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'imports', data = data.sort_values(ascending = False,by = 'imports').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Imports (%)')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **imports** stats of a nation describe the self reliance of a nation to solve their problems irrespective of being handicapped on one of the essential resources.\n",
    "- **Singapore**, **Malta**, **Luxembourg** & **Seychelles** are present in the top 5 of **exports** as well as **imports**. This is just an indication that highlight the nation's strategies of probably capitalizing on their resources and creating solid **exports** that gets countered by the heavy **imports** on something else. This just balances the books!\n",
    "- **Brazil** has the lowest **imports** out of all the nations with **11%**. **Sudan** is the only African country present in this lower end list with **17%**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **income : Income of the per person is a key indicator about country's economic state. Higher the income of the citizens, more capabale they are to deal with uncertain situations!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:10.996088Z",
     "iopub.status.busy": "2022-10-21T12:53:10.995663Z",
     "iopub.status.idle": "2022-10-21T12:53:11.819189Z",
     "shell.execute_reply": "2022-10-21T12:53:11.817680Z",
     "shell.execute_reply.started": "2022-10-21T12:53:10.996054Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'income', data = data.sort_values(ascending = False,by = 'income').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Income/Person')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'income', data = data.sort_values(ascending = False,by = 'income').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Income/Person')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'income', data = data.sort_values(ascending = False,by = 'income').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Income/Person')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Citizens of the **Qatar** have the highest **income** out of all the countries with a difference of **30k** more than the 2nd placed countries. **Singapore** & **Luxembourg** are again present in the top 5 of another feature.\n",
    "- Lower end of the **income** is dominated by the **African** nations. This is influenced by the damage done by colonization out of which the nations have not yet recovered. \n",
    "- The difference in the **income** of the nations in the top, middle and lower end is quite significant that will have an effect on every other features."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **inflation : It dictates the state of the economy, strength of the currency as well as demand for goods & services!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:13.403418Z",
     "iopub.status.busy": "2022-10-21T12:53:13.402961Z",
     "iopub.status.idle": "2022-10-21T12:53:13.967973Z",
     "shell.execute_reply": "2022-10-21T12:53:13.966519Z",
     "shell.execute_reply.started": "2022-10-21T12:53:13.403383Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'inflation', data = data.sort_values(ascending = False,by = 'inflation').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Inflation')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'inflation', data = data.sort_values(ascending = False,by = 'inflation').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Inflation')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'inflation', data = data.sort_values(ascending = False,by = 'inflation').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Inflation')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Higher **inflation** reduces the purchasing power of the citizens. Countries present at the top end of **inflation** have a devastating economic situation. Having such high inflation is a risk to the existence of the nation.\n",
    "- Similarly, the lower end of **inflation** has negative values i.e known as deflation. It signals a economy in a downward spiral leading to a recession or even a depression."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **life_expec : Higher life expectancy displays citizens with health attributes physically as well as mentally!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:15.772249Z",
     "iopub.status.busy": "2022-10-21T12:53:15.771787Z",
     "iopub.status.idle": "2022-10-21T12:53:16.289546Z",
     "shell.execute_reply": "2022-10-21T12:53:16.288387Z",
     "shell.execute_reply.started": "2022-10-21T12:53:15.772213Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'life_expec', data = data.sort_values(ascending = False,by = 'life_expec').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Life Expectancy')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'life_expec', data = data.sort_values(ascending = False,by = 'life_expec').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Life Expectancy')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'life_expec', data = data.sort_values(ascending = False,by = 'life_expec').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Life Expectancy')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **life_expec** depends alot on mental state as well as the lifestyle adopted by the citizens. **Singapore** is again present in the top of 5 of a feature.\n",
    "- None of the countries with a high **life_expec** are present in the top 5 of **health** that is related to the spending done by the citizen on health.\n",
    "- **African** countries are again present in the lower end for another feature."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **total_fer : Economically backward countries have a high fertility rate!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:17.816504Z",
     "iopub.status.busy": "2022-10-21T12:53:17.815777Z",
     "iopub.status.idle": "2022-10-21T12:53:18.422242Z",
     "shell.execute_reply": "2022-10-21T12:53:18.420560Z",
     "shell.execute_reply.started": "2022-10-21T12:53:17.816468Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'total_fer', data = data.sort_values(ascending = False,by = 'total_fer').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High Female Fertility Rate')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'total_fer', data = data.sort_values(ascending = False,by = 'total_fer').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial Female Fertility Rate')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'total_fer', data = data.sort_values(ascending = False,by = 'total_fer').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low Female Fertility Rate')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **African** countries dominate the **total_fer** with values **6+**.\n",
    "- Mean **total_fer** value is **2** whereas lower end values of **1** concern abit as well."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **gdpp : It is a feature that provides information about the contribution of a citizen to it's GDP!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:21.405915Z",
     "iopub.status.busy": "2022-10-21T12:53:21.405446Z",
     "iopub.status.idle": "2022-10-21T12:53:21.992757Z",
     "shell.execute_reply": "2022-10-21T12:53:21.991150Z",
     "shell.execute_reply.started": "2022-10-21T12:53:21.405878Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.subplots(nrows = 1,ncols = 3,figsize = (25,7))\n",
    "plt.subplot(1,3,1)\n",
    "ax = sns.barplot(x = 'country',y = 'gdpp', data = data.sort_values(ascending = False,by = 'gdpp').iloc[:5],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with High GDP Contribution /Person')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,2)\n",
    "ax = sns.barplot(x = 'country',y = 'gdpp', data = data.sort_values(ascending = False,by = 'gdpp').iloc[81:86],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Medial GDP Contribution /Person')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "\n",
    "plt.subplot(1,3,3)\n",
    "ax = sns.barplot(x = 'country',y = 'gdpp', data = data.sort_values(ascending = False,by = 'gdpp').iloc[161:166],palette = colors,edgecolor = 'black');\n",
    "plt.title('Countries with Low GDP Contribution /Person')\n",
    "for rect in ax.patches:\n",
    "    ax.text(rect.get_x() + rect.get_width()/2, rect.get_height(), int(rect.get_height()), \n",
    "            horizontalalignment='center', fontsize = 12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- It is a tricky feature as the population of the nation is a significant factor. One clear cut example of this is **China**. It has a huge population alongwith huge GDP.\n",
    "- **Luxembourg** is again present in the top ranks. **Switzerland** & **Qatar** are present in the top 5 similar to **income**.\n",
    "- Lower end is again dominated by **African** nations that labels them as the economically backward."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Numerical Features :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:24.258201Z",
     "iopub.status.busy": "2022-10-21T12:53:24.257779Z",
     "iopub.status.idle": "2022-10-21T12:53:25.135813Z",
     "shell.execute_reply": "2022-10-21T12:53:25.132767Z",
     "shell.execute_reply.started": "2022-10-21T12:53:24.258167Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig  = plt.subplots(nrows = 3,ncols = 3,figsize = (15,15))\n",
    "for i in range(len(numerical_features)):\n",
    "    plt.subplot(3,3,i+1)\n",
    "    ax = sns.boxplot(data[numerical_features[i]],color = colors[0])\n",
    "    plt.title(numerical_features[i])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Summary EDA</div></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the visualizations and the list of features of an economically backward nations, a host of insights can be gained!\n",
    "- When it comes to health conditions, **African countries** hold higher ranks in all the wrong situations. They hold a significant presence in high **child_mort**, low **life_expec** and high **total_fer**. \n",
    "- All these problems are already pretty serious and hence it is very important to assist them during the periods of unforseen turmoils. Despite such numbers, **Haiti** grabs the top spot with high values of  **child_mort**. **Asian & European countries** are present at the other end of it. \n",
    "- **US** citizens are the highest spenders on their **health** however they are not present in the top 5 ranks of **life_expec** & **total_fer**. None of the countries with a high **life_expec** are present in the top 5 of **health**. **Asian countries** crowd lower end of **health**. \n",
    "- **Singapore**, **Malta**, **Luxembourg** & **Seychelles** are present in the top 5 of **exports** as well as **imports**. Population size and geographical locations play a pivotal role when it comes to **imports** and **exports**. \n",
    "- **Sudan** is the only **African** nation with low **imports** and **Brazil** has the lowest imports out of all.\n",
    "- **African countries** display very high values of **inflation** whereas countries from all the continents can be found with low **inflation** values.\n",
    "- Citizens of the **Qatar** are the highest paid with **Singapore** & **Luxembourg** again grabbing spots in top 5 of **income**.\n",
    "- For **gdpp**, **Luxembourg** is in the top ranks. **Switzerland** & **Qatar** are present in the top 5 similar to **income**.\n",
    "- **African nations** are present in the lower end of **income** as well as **gdpp**. Colonization has had a huge toll on the **African nations**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Feature Engineering</div></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Correlation Matrix :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:29.351107Z",
     "iopub.status.busy": "2022-10-21T12:53:29.350628Z",
     "iopub.status.idle": "2022-10-21T12:53:30.623726Z",
     "shell.execute_reply": "2022-10-21T12:53:30.622634Z",
     "shell.execute_reply.started": "2022-10-21T12:53:29.351052Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "ut = np.triu(data.corr())\n",
    "lt = np.tril(data.corr())\n",
    "\n",
    "fig,ax = plt.subplots(nrows = 1, ncols = 2,figsize = (15,5))\n",
    "plt.subplot(1,2,1)\n",
    "sns.heatmap(data.corr(),cmap = colors,annot = True,cbar = 'True',mask = ut);\n",
    "plt.title('Correlation Matrix : Upper Triangular Format');\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.heatmap(data.corr(),cmap = colors,annot = True,cbar = 'True',mask = lt);\n",
    "plt.title('Correlation Matrix : Lower Triangular Format');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Many features have relationships with each other.\n",
    "- **child_mort** clearly increases when **income**, **gdpp** & **exports** decreases. Rise in **inflation** also leads to high **child_mort** cases. Economic conditions unfortunately act as an important factor!\n",
    "- Rise in **exports** clearly increases **gdpp**, **income** & **imports**.\n",
    "- Spending on **health** has a small rise in **life_expec** and also decreases the **child_mort**.\n",
    "- **income** & **gdpp** display a very high 0.9 correlation value. From the health perspective, high **income** has lead to higher **life_expec** but decreases the **total_fer** by some significant margin.\n",
    "- As expected high **inflation** has a negative effect on the financial features. High **inflation** displays a high **total_fer** and **child_mort**. This describes the typical features of a backward nation.\n",
    "- According to the data, higher **life_expec** displays a low **total_fer**. Higher **gdpp** has lead more spending on **health**. \n",
    "\n",
    "**We can clearly see that some features are essentially from the same category and they have the same reaction to other features of different category.**\n",
    "- The 3 categories of the features are :\n",
    "    - **health** : **child_mort**, **health**, **life_expec**, **total_fer**\n",
    "    - **trade** : **imports**, **exports**\n",
    "    - **finance** : **income**, **inflation**, **gdpp**\n",
    "- Hence, we will dissolve these features into these categories and normalize them!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:32.868812Z",
     "iopub.status.busy": "2022-10-21T12:53:32.868027Z",
     "iopub.status.idle": "2022-10-21T12:53:32.892051Z",
     "shell.execute_reply": "2022-10-21T12:53:32.890280Z",
     "shell.execute_reply.started": "2022-10-21T12:53:32.868766Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "df1 = pd.DataFrame()\n",
    "df1['Health'] = (data['child_mort'] / data['child_mort'].mean()) + (data['health'] / data['health'].mean()) + (data['life_expec'] / data['life_expec'].mean()) + (data['total_fer'] / data['total_fer'].mean())\n",
    "df1['Trade'] = (data['imports'] / data['imports'].mean()) + (data['exports'] / data['exports'].mean())\n",
    "df1['Finance'] = (data['income'] / data['income'].mean()) + (data['inflation'] / data['inflation'].mean()) + (data['gdpp'] / data['gdpp'].mean())\n",
    "df1.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data Scaling :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:35.465638Z",
     "iopub.status.busy": "2022-10-21T12:53:35.465230Z",
     "iopub.status.idle": "2022-10-21T12:53:35.493284Z",
     "shell.execute_reply": "2022-10-21T12:53:35.491927Z",
     "shell.execute_reply.started": "2022-10-21T12:53:35.465606Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler,StandardScaler\n",
    "mms = MinMaxScaler() # Normalization\n",
    "ss = StandardScaler() # Standardization\n",
    "\n",
    "df1['Health'] = mms.fit_transform(df1[['Health']])\n",
    "df1['Trade'] = mms.fit_transform(df1[['Trade']])\n",
    "df1['Finance'] = mms.fit_transform(df1[['Finance']])\n",
    "df1.insert(loc = 0, value = list(data['country']), column = 'Country')\n",
    "df1.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Machine learning model does not understand the units of the values of the features. It treats the input just as a simple number but does not understand the true meaning of that value. Thus, it becomes necessary to scale the data.\n",
    "\n",
    "**Eg :** Age = Years; FastingBS = mg / dl; Charges = Currency \n",
    "\n",
    "- We have 2 options for data scaling : 1) **Normalization** 2) **Standardization**. As most of the algorithms assume the data to be normally (Gaussian) distributed, **Normalization** is done for features whose data does not display normal distribution and **standardization** is carried out for features that are normally distributed where their values are huge or very small as compared to other features.\n",
    "\n",
    "\n",
    "- **Normalization** : **Health**, **Trade** and **Finance** features are normalized!\n",
    "\n",
    "\n",
    "- **Standardization** : None of the features are standardized for the above data."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Principal Component Analysis (PCA) :\n",
    "\n",
    "- It is a dimension reduction method that is preferrably used for an Unsupervised Learning Problem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:40.082757Z",
     "iopub.status.busy": "2022-10-21T12:53:40.081329Z",
     "iopub.status.idle": "2022-10-21T12:53:40.134056Z",
     "shell.execute_reply": "2022-10-21T12:53:40.132539Z",
     "shell.execute_reply.started": "2022-10-21T12:53:40.082708Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "df2 = data.copy(deep = True)\n",
    "\n",
    "col = list(data.columns)\n",
    "col.remove('health'); col.remove('country')\n",
    "\n",
    "df2['health'] = ss.fit_transform(df2[['health']]) # Standardization\n",
    "\n",
    "for i in col:\n",
    "    df2[i] = mms.fit_transform(df2[[i]]) # Normalization\n",
    "df2.drop(columns = 'country',inplace = True) \n",
    "df2.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Before passing the data for PCA transformation, **normalization** & **standardization** are very important."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:44.132810Z",
     "iopub.status.busy": "2022-10-21T12:53:44.132342Z",
     "iopub.status.idle": "2022-10-21T12:53:44.157090Z",
     "shell.execute_reply": "2022-10-21T12:53:44.155541Z",
     "shell.execute_reply.started": "2022-10-21T12:53:44.132774Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "\n",
    "pca = PCA()\n",
    "pca_df2 = pd.DataFrame(pca.fit_transform(df2))\n",
    "pca.explained_variance_"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- These are the variance values of the each feature present in the dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:46.964983Z",
     "iopub.status.busy": "2022-10-21T12:53:46.964509Z",
     "iopub.status.idle": "2022-10-21T12:53:47.176378Z",
     "shell.execute_reply": "2022-10-21T12:53:47.175147Z",
     "shell.execute_reply.started": "2022-10-21T12:53:46.964950Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "plt.step(list(range(1,10)), np.cumsum(pca.explained_variance_ratio_))\n",
    "plt.plot(np.cumsum(pca.explained_variance_ratio_))\n",
    "plt.xlabel('Eigen Values')\n",
    "plt.ylabel('Ratio of Variance Explained')\n",
    "plt.title('Variance Covered by each Eigen Value')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- This is a very effective method where we add up the variances of all the features in cummulative format.\n",
    "- Typically **eigen values with more than 95% of ratio of variance** are selected.\n",
    "- They correspond to the columns of the PCA generated dataframe.\n",
    "- In this case, we select the **Eigen Value : 2** as the steps generated have significant variances and thus the other features get dominated by their variances. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:49.102367Z",
     "iopub.status.busy": "2022-10-21T12:53:49.101351Z",
     "iopub.status.idle": "2022-10-21T12:53:49.117284Z",
     "shell.execute_reply": "2022-10-21T12:53:49.115884Z",
     "shell.execute_reply.started": "2022-10-21T12:53:49.102303Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "pca_df2 = pca_df2.drop(columns = [3,4,5,6,7,8])\n",
    "pca_df2.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **In this way, we reduce the dimensions! We will now move on to the modeling section and compare the performances of the 2 datasets :**\n",
    "    - **Feature Combination : Health - Trade - Finance**\n",
    "    - **PCA Data**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Modeling</div></center>\n",
    "\n",
    "- **Unsupervised Learning** : It is a problem where the target variable / feature is unknown. **Unsupervised Learning** problems widely occur in medical domain where mutliple readings are taken and the underlying diseases are unknown. \n",
    "- Thus, searching for patterns by using visualization techniques provides us with some underlying insight that cannot be understood by staring into the tabular data.\n",
    "- However, when the size of the datasets becomes huge with too many features, data visualization can be a tedious task to execute. Hence, we move towards the algorithmic approach."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:51.731309Z",
     "iopub.status.busy": "2022-10-21T12:53:51.730864Z",
     "iopub.status.idle": "2022-10-21T12:53:51.739050Z",
     "shell.execute_reply": "2022-10-21T12:53:51.737603Z",
     "shell.execute_reply.started": "2022-10-21T12:53:51.731275Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "m1 = df1.drop(columns = ['Country']).values # Feature Combination : Health - Trade - Finance\n",
    "m2 = pca_df2.values # PCA Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <center>K-Means Clustering</center>\n",
    "\n",
    "**K-Means Clustering** is a distance based algorithm that is used for unsupervised learning that **does not support categorical features**. \n",
    "- It is the most preferred algorithm for dealing with **Unsupervised Learning** that does the job of finding clusters the in data but with a mathematical approach :\n",
    "    - Selects 2 (assume k = 2) centroids randomly.\n",
    "    - Distance between the centroids and all the data points are calculated.\n",
    "    - If the data point is closer to one of the centroids, then it gets labelled as that centroid and vice-versa.\n",
    "    - For the 2 clusters formed, average value of the data points, grouped with either of the centroid, is calculated and these average values are then defined as the new clusters.\n",
    "    - This process repeats itself untill both centroids converge to fixed points.\n",
    "- **k hyperparameter** : It defines the number of clusters or groups the data is to be divided into. For the selection of values of **k**, we use 2 statistical tests :\n",
    "    - **Elbow Method** : It is a method that plots the sum of squared error for a range of values of **k**. If this plot looks like an arm, then **k** is the value that resembles an **elbow** is selected. From this **elbow** value, sum of squared values (inertia) starts decreasing in a linear fashion and thus is considered as an optimal value.\n",
    "    - **Silhouette Score Method** : It is a method that evaluates the quality of clusters in terms of how well data points are clustered with other data points that are similar to each other. This score is calculated using the distance formula and the **k** value with highest score is selected for modeling."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>Feature Combination : Health - Trade - Finance</center> "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Elbow Method & Silhouette Score Method :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:53:55.588030Z",
     "iopub.status.busy": "2022-10-21T12:53:55.587556Z",
     "iopub.status.idle": "2022-10-21T12:53:57.656704Z",
     "shell.execute_reply": "2022-10-21T12:53:57.655062Z",
     "shell.execute_reply.started": "2022-10-21T12:53:55.587994Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "sse = {};sil = [];kmax = 10\n",
    "fig = plt.subplots(nrows = 1, ncols = 2, figsize = (20,5))\n",
    "\n",
    "# Elbow Method :\n",
    "plt.subplot(1,2,1)\n",
    "for k in range(1, 10):\n",
    "    kmeans = KMeans(n_clusters=k, max_iter=1000).fit(m1)\n",
    "    sse[k] = kmeans.inertia_ # Inertia: Sum of distances of samples to their closest cluster center\n",
    "sns.lineplot(x = list(sse.keys()), y = list(sse.values()));\n",
    "plt.title('Elbow Method')\n",
    "plt.xlabel(\"k : Number of cluster\")\n",
    "plt.ylabel(\"Sum of Squared Error\")\n",
    "plt.grid()\n",
    "\n",
    "# Silhouette Score Method\n",
    "plt.subplot(1,2,2)\n",
    "for k in range(2, kmax + 1):\n",
    "    kmeans = KMeans(n_clusters = k).fit(m1)\n",
    "    labels = kmeans.labels_\n",
    "    sil.append(silhouette_score(m1, labels, metric = 'euclidean'))\n",
    "sns.lineplot(x = range(2,kmax + 1), y = sil);\n",
    "plt.title('Silhouette Score Method')\n",
    "plt.xlabel(\"k : Number of cluster\")\n",
    "plt.ylabel(\"Silhouette Score\")\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the results of the above 2 methods, we select :\n",
    "    - **k : Clusters = 3**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:54:00.923703Z",
     "iopub.status.busy": "2022-10-21T12:54:00.923193Z",
     "iopub.status.idle": "2022-10-21T12:54:01.156801Z",
     "shell.execute_reply": "2022-10-21T12:54:01.155259Z",
     "shell.execute_reply.started": "2022-10-21T12:54:00.923658Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "model = KMeans(n_clusters = 3,max_iter = 1000)\n",
    "model.fit(m1)\n",
    "cluster = model.cluster_centers_\n",
    "centroids = np.array(cluster)\n",
    "labels = model.labels_\n",
    "data['Class'] = labels; df1['Class'] = labels\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = Axes3D(fig)\n",
    "x = np.array(df1['Health'])\n",
    "y = np.array(df1['Trade'])\n",
    "z = np.array(df1['Finance'])\n",
    "ax.scatter(centroids[:,0],centroids[:,1],centroids[:,2],marker=\"X\", color = 'b')\n",
    "ax.scatter(x,y,z,c = y)\n",
    "plt.title('Health vs Trade vs Finance')\n",
    "ax.set_xlabel('Health')\n",
    "ax.set_ylabel('Trade')\n",
    "ax.set_zlabel('Finance')\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Now we have got the clusters but we don't know which value corresponds to what! \n",
    "- Hence, we draw a boxplot of **income** & **child_mort** w.r.t labelled clusters!\n",
    "- We know that **low income and high child mortality** is a sign of an **economically backward nation**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:54:04.266216Z",
     "iopub.status.busy": "2022-10-21T12:54:04.264820Z",
     "iopub.status.idle": "2022-10-21T12:54:04.613535Z",
     "shell.execute_reply": "2022-10-21T12:54:04.611964Z",
     "shell.execute_reply.started": "2022-10-21T12:54:04.266155Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15,5))\n",
    "\n",
    "plt.subplot(1,2,1)\n",
    "sns.boxplot(x = 'Class', y = 'child_mort', data  = data, color = '#FF781F');\n",
    "plt.title('child_mort vs Class')\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.boxplot(x = 'Class', y = 'income', data  = data, color = '#FF781F');\n",
    "plt.title('income vs Class')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the above plot we can conclude :\n",
    "    - **0 : No Help Needed**\n",
    "    - **1 : Help Needed**\n",
    "    - **2 : Might Need Help**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:54:51.827450Z",
     "iopub.status.busy": "2022-10-21T12:54:51.827002Z",
     "iopub.status.idle": "2022-10-21T12:54:52.951552Z",
     "shell.execute_reply": "2022-10-21T12:54:52.950060Z",
     "shell.execute_reply.started": "2022-10-21T12:54:51.827415Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "df1['Class'].loc[df1['Class'] == 0] = 'No Help Needed'\n",
    "df1['Class'].loc[df1['Class'] == 1] = 'Help Needed'\n",
    "df1['Class'].loc[df1['Class'] == 2] = 'Might Need Help'\n",
    "\n",
    "fig = px.choropleth(df1[['Country','Class']],\n",
    "                    locationmode = 'country names',\n",
    "                    locations = 'Country',\n",
    "                    title = 'Needed Help Per Country (World)',\n",
    "                    color = df1['Class'],  \n",
    "                    color_discrete_map = {'Help Needed':'Red',\n",
    "                                        'No Help Needed':'Green',\n",
    "                                        'Might Need Help':'Yellow'}\n",
    "                   )\n",
    "fig.update_geos(fitbounds = \"locations\", visible = True)\n",
    "fig.update_layout(legend_title_text = 'Labels',legend_title_side = 'top',title_pad_l = 260,title_y = 0.86)\n",
    "fig.show(engine = 'kaleido')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>PCA Data</center> "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Elbow Method & Silhouette Score Method :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:54:56.567684Z",
     "iopub.status.busy": "2022-10-21T12:54:56.567262Z",
     "iopub.status.idle": "2022-10-21T12:54:58.442198Z",
     "shell.execute_reply": "2022-10-21T12:54:58.440959Z",
     "shell.execute_reply.started": "2022-10-21T12:54:56.567650Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "sse = {};sil = [];kmax = 10\n",
    "fig = plt.subplots(nrows = 1, ncols = 2, figsize = (20,5))\n",
    "\n",
    "# Elbow Method :\n",
    "plt.subplot(1,2,1)\n",
    "for k in range(1, 10):\n",
    "    kmeans = KMeans(n_clusters=k, max_iter=1000).fit(m2)\n",
    "    sse[k] = kmeans.inertia_ # Inertia: Sum of distances of samples to their closest cluster center\n",
    "sns.lineplot(x = list(sse.keys()), y = list(sse.values()));\n",
    "plt.title('Elbow Method')\n",
    "plt.xlabel(\"k : Number of cluster\")\n",
    "plt.ylabel(\"Sum of Squared Error\")\n",
    "plt.grid()\n",
    "\n",
    "# Silhouette Score Method\n",
    "plt.subplot(1,2,2)\n",
    "for k in range(2, kmax + 1):\n",
    "    kmeans = KMeans(n_clusters = k).fit(m2)\n",
    "    labels = kmeans.labels_\n",
    "    sil.append(silhouette_score(m2, labels, metric = 'euclidean'))\n",
    "sns.lineplot(x = range(2,kmax + 1), y = sil);\n",
    "plt.title('Silhouette Score Method')\n",
    "plt.xlabel(\"k : Number of cluster\")\n",
    "plt.ylabel(\"Silhouette Score\")\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the results of the above 2 methods, we select :\n",
    "    - **k : Clusters = 3**        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:54:58.445079Z",
     "iopub.status.busy": "2022-10-21T12:54:58.443891Z",
     "iopub.status.idle": "2022-10-21T12:54:58.723656Z",
     "shell.execute_reply": "2022-10-21T12:54:58.722523Z",
     "shell.execute_reply.started": "2022-10-21T12:54:58.445036Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "model = KMeans(n_clusters = 3,max_iter = 1000)\n",
    "model.fit(m2)\n",
    "cluster = model.cluster_centers_\n",
    "centroids = np.array(cluster)\n",
    "labels = model.labels_\n",
    "data['Class'] = labels; pca_df2['Class'] = labels\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = Axes3D(fig)\n",
    "ax.scatter(centroids[:,0],centroids[:,1],centroids[:,2],marker=\"X\", color = 'b')\n",
    "plt.title('PCA Data')\n",
    "ax.set_xlabel('0th Component')\n",
    "ax.set_ylabel('1st Component')\n",
    "ax.set_zlabel('2nd Component')\n",
    "ax.scatter(x,y,z,c = y)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- We again check the scatterplot of **income** & **child_mort** w.r.t labelled clusters for confirming the cluster values!\n",
    "- We know that **low income and high child mortality** is a sign of an **economically backward nation**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:05.160890Z",
     "iopub.status.busy": "2022-10-21T12:55:05.159888Z",
     "iopub.status.idle": "2022-10-21T12:55:05.701403Z",
     "shell.execute_reply": "2022-10-21T12:55:05.700637Z",
     "shell.execute_reply.started": "2022-10-21T12:55:05.160852Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15,5))\n",
    "\n",
    "plt.subplot(1,2,1)\n",
    "sns.boxplot(x = 'Class', y = 'child_mort', data  = data, color = '#FF781F');\n",
    "plt.title('child_mort vs Class')\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.boxplot(x = 'Class', y = 'income', data  = data, color = '#FF781F');\n",
    "plt.title('income vs Class')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the above plot we can conclude :\n",
    "    - **0 : Might Need Help**\n",
    "    - **1 : Help Needed**\n",
    "    - **2 : No Help Needed**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:14.529517Z",
     "iopub.status.busy": "2022-10-21T12:55:14.529065Z",
     "iopub.status.idle": "2022-10-21T12:55:14.613931Z",
     "shell.execute_reply": "2022-10-21T12:55:14.612629Z",
     "shell.execute_reply.started": "2022-10-21T12:55:14.529483Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "pca_df2.insert(0,column = 'Country', value = data['country'])\n",
    "\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 0] = 'Might Need Help'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 1] = 'Help Needed'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 2] = 'No Help Needed'\n",
    "\n",
    "fig = px.choropleth(pca_df2[['Country','Class']],\n",
    "                    locationmode = 'country names',\n",
    "                    locations = 'Country',\n",
    "                    title = 'Needed Help Per Country (World)',\n",
    "                    color = pca_df2['Class'],  \n",
    "                    color_discrete_map = {'Help Needed':'Red',\n",
    "                                          'Might Need Help':'Yellow',\n",
    "                                          'No Help Needed': 'Green'})\n",
    "fig.update_geos(fitbounds = \"locations\", visible = True)\n",
    "fig.update_layout(legend_title_text = 'Labels',legend_title_side = 'top',title_pad_l = 260,title_y = 0.86)\n",
    "fig.show(engine = 'kaleido')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <center>Density Based Spatial Clustering of Application with Noise Clustering</center>\n",
    "\n",
    "**DBSCAN Clustering** is a density based clustering algorithm that is used for unsupervised learning problems.\n",
    "- In a bid to eliminate the problems of **K-Means Clustering** with nested data and high-dimensional data, **DBSCAN Clustering** eliminates it! It's has 3 important terms & 2 important hyperparameters :\n",
    "    - Terms :\n",
    "        - **Core Point** : It is the center point that has **minPts** number of data points present in it's area and the points under it's area can extend the cluster.\n",
    "        - **Non-Core Point** : It is the center point that does not have **minPts** number of data points present in it's area and it cannot extend the cluster.\n",
    "        - **Outliers / Noise** : It is the data points that are not a part of any cluster.\n",
    "    - Hyperparameters :\n",
    "        - **minPts** : It is the minimum number of data points that need to be present in the area of a point to be considered as a core point.\n",
    "        - **Epsilon** : It is the radius of the area of a center point.\n",
    "- **DBSCAN Clustering** creates the clusters in the following way :        \n",
    "    - Select a random point and consider it as a center point from the data. \n",
    "    - Check the other data points that present in the area of this center point with the **Epsilon** value as it's radius.\n",
    "    - If this area has **minPts** number of data points in it, then the center point is considered as a **core point**. \n",
    "    - The data points in this area are then considered as **core point** that further extends by the same rules creating a cluster. \n",
    "    - If any of the point does not satisfy the rules, it is considered as **non-core point** that remains the part of the cluster but it cannot extend the cluster further.\n",
    "    - When all the **core points** are done with engulfing the other data points, **non-core points** are included & the cluster is completed.\n",
    "    - The next cluster then starts forming by the same rules. Some of the points don't be a part of any of the clusters, such points are known as **outliers / noise**.\n",
    "- As you might have noticed, the hyperparameters play a crucical role in this process. Thus, they have certain rules for assigning them values :\n",
    "    - **minPts** : If D represents the number of dimensions / features of a dataset, then **minPts** >= D + 1. Typically **minPts** >= 2 * D is selected for smaller or noisy datasets. \n",
    "    - **Epsilon** : It's value is usually decided using the **k-distance graph** that is determined from the **KNN model**. The value at which the graph changes sharply is selected."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:19.838476Z",
     "iopub.status.busy": "2022-10-21T12:55:19.838008Z",
     "iopub.status.idle": "2022-10-21T12:55:19.844649Z",
     "shell.execute_reply": "2022-10-21T12:55:19.843518Z",
     "shell.execute_reply.started": "2022-10-21T12:55:19.838441Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from sklearn.cluster import DBSCAN\n",
    "from sklearn.neighbors import NearestNeighbors"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>Feature Combination : Health - Trade - Finance</center> "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:22.399703Z",
     "iopub.status.busy": "2022-10-21T12:55:22.399245Z",
     "iopub.status.idle": "2022-10-21T12:55:22.643324Z",
     "shell.execute_reply": "2022-10-21T12:55:22.642145Z",
     "shell.execute_reply.started": "2022-10-21T12:55:22.399667Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "knn = NearestNeighbors(n_neighbors = 7)\n",
    "model = knn.fit(m1)\n",
    "distances, indices = knn.kneighbors(m1)\n",
    "distances = np.sort(distances, axis=0)\n",
    "distances = distances[:,1]\n",
    "plt.grid()\n",
    "plt.plot(distances);\n",
    "plt.xlabel('Points Sorted by Distance')\n",
    "plt.ylabel('7-NN Distance')\n",
    "plt.title('K-Distance Graph');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- We select **minPts** = 8 i.e >= 2 * 3 features \n",
    "- The value assigned to the **n_neighbors** : **minPts** - 1.\n",
    "- From the graph above, we select :\n",
    "    - **eps** : 0.08"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:27.057158Z",
     "iopub.status.busy": "2022-10-21T12:55:27.056744Z",
     "iopub.status.idle": "2022-10-21T12:55:27.071216Z",
     "shell.execute_reply": "2022-10-21T12:55:27.069567Z",
     "shell.execute_reply.started": "2022-10-21T12:55:27.057126Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "db = DBSCAN(eps = 0.080, min_samples = 8).fit(m1)\n",
    "core_samples_mask = np.zeros_like(db.labels_, dtype=bool)\n",
    "core_samples_mask[db.core_sample_indices_] = True\n",
    "labels = db.labels_\n",
    "\n",
    "# Number of clusters in labels, ignoring noise if present\n",
    "\n",
    "n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)\n",
    "n_noise_ = list(labels).count(-1)\n",
    "print('Number of Clusters : ', n_clusters_)\n",
    "print('Number of Outliers : ', n_noise_)\n",
    "\n",
    "data['Class'] = labels; df1['Class'] = labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:30.124637Z",
     "iopub.status.busy": "2022-10-21T12:55:30.124136Z",
     "iopub.status.idle": "2022-10-21T12:55:30.334965Z",
     "shell.execute_reply": "2022-10-21T12:55:30.333754Z",
     "shell.execute_reply.started": "2022-10-21T12:55:30.124596Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "unique_labels = set(labels)\n",
    "colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))]\n",
    "for k, col in zip(unique_labels, colors):\n",
    "    if k == -1:\n",
    "        # Black used for noise.\n",
    "        col = [0, 0, 0, 1]\n",
    "    class_member_mask = labels == k\n",
    "\n",
    "    xy = m1[class_member_mask & core_samples_mask]\n",
    "    plt.plot(xy[:, 0], xy[:, 1], \"o\", markerfacecolor = tuple(col), markeredgecolor = \"k\", markersize = 14)\n",
    "\n",
    "    xy = m1[class_member_mask & ~core_samples_mask]\n",
    "    plt.plot(xy[:, 0], xy[:, 1], \"o\", markerfacecolor = tuple(col), markeredgecolor = \"k\", markersize = 6)\n",
    "\n",
    "plt.title(\"Estimated number of clusters: %d\" % n_clusters_)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Now we have got the clusters but we don't know which value corresponds to what! \n",
    "- Hence, we draw a boxplots of **income** & **child_mort** w.r.t labelled clusters!\n",
    "- We know that **low income and high child mortality** is a sign of an **economically backward nation**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:33.236120Z",
     "iopub.status.busy": "2022-10-21T12:55:33.235143Z",
     "iopub.status.idle": "2022-10-21T12:55:33.596391Z",
     "shell.execute_reply": "2022-10-21T12:55:33.595559Z",
     "shell.execute_reply.started": "2022-10-21T12:55:33.236083Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15,5))\n",
    "\n",
    "plt.subplot(1,2,1)\n",
    "sns.boxplot(x = 'Class', y = 'child_mort', data  = data, color = '#FF781F');\n",
    "plt.title('child_mort vs Class')\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.boxplot(x = 'Class', y = 'income', data  = data, color = '#FF781F');\n",
    "plt.title('income vs Class')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- By rule **-1** is associated with **Noise / Outliers**!\n",
    "- From the above plot we can conclude :\n",
    "    - **-1 : Noise / Outliers**\n",
    "    - **0 : Might Need Help**\n",
    "    - **1 : No Help Needed**\n",
    "    - **2 : Help Needed**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:43.579738Z",
     "iopub.status.busy": "2022-10-21T12:55:43.579217Z",
     "iopub.status.idle": "2022-10-21T12:55:43.669820Z",
     "shell.execute_reply": "2022-10-21T12:55:43.668648Z",
     "shell.execute_reply.started": "2022-10-21T12:55:43.579695Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "df1['Class'].loc[df1['Class'] == -1] = 'Noise / Outliers'\n",
    "df1['Class'].loc[df1['Class'] == 0] = 'Might Need Help'\n",
    "df1['Class'].loc[df1['Class'] == 1] = 'No Help Needed'\n",
    "df1['Class'].loc[df1['Class'] == 2] ='Help Needed'\n",
    "\n",
    "fig = px.choropleth(df1[['Country','Class']],\n",
    "                    locationmode = 'country names',\n",
    "                    locations = 'Country',\n",
    "                    title = 'Needed Help Per Country (World)',\n",
    "                    color = df1['Class'],  \n",
    "                    color_discrete_map={'Noise / Outliers' : 'Black',\n",
    "                                        'Help Needed':'Red',\n",
    "                                        'Might Need Help':'Yellow',\n",
    "                                        'No Help Needed':'Green'})\n",
    "fig.update_geos(fitbounds = \"locations\", visible = True)\n",
    "fig.update_layout(legend_title_text = 'Labels',legend_title_side = 'top',title_pad_l = 260,title_y = 0.86)\n",
    "fig.show(engine = 'kaleido')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>PCA Data</center> "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:47.172879Z",
     "iopub.status.busy": "2022-10-21T12:55:47.172368Z",
     "iopub.status.idle": "2022-10-21T12:55:47.439129Z",
     "shell.execute_reply": "2022-10-21T12:55:47.437929Z",
     "shell.execute_reply.started": "2022-10-21T12:55:47.172839Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "knn = NearestNeighbors(n_neighbors = 7)\n",
    "model = knn.fit(m2)\n",
    "distances, indices = knn.kneighbors(m2)\n",
    "distances = np.sort(distances, axis=0)\n",
    "distances = distances[:,1]\n",
    "plt.xlabel('Points Sorted by Distance')\n",
    "plt.ylabel('7-NN Distance')\n",
    "plt.title('K-Distance Graph');\n",
    "plt.grid()\n",
    "plt.plot(distances);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- We select **minPts** = 8 i.e >= 2 * 3 features \n",
    "- The value assigned to the **n_neighbors** : **minPts** - 1.\n",
    "- From the graph above, we select :\n",
    "    - **eps** : 0.08"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:50.494388Z",
     "iopub.status.busy": "2022-10-21T12:55:50.493982Z",
     "iopub.status.idle": "2022-10-21T12:55:50.507929Z",
     "shell.execute_reply": "2022-10-21T12:55:50.506081Z",
     "shell.execute_reply.started": "2022-10-21T12:55:50.494354Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "db = DBSCAN(eps = 0.2, min_samples = 8).fit(m2)\n",
    "core_samples_mask = np.zeros_like(db.labels_, dtype=bool)\n",
    "core_samples_mask[db.core_sample_indices_] = True\n",
    "labels = db.labels_\n",
    "\n",
    "# Number of clusters in labels, ignoring noise if present\n",
    "n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)\n",
    "n_noise_ = list(labels).count(-1)\n",
    "print('Number of Clusters : ', n_clusters_)\n",
    "print('Number of Outliers : ', n_noise_)\n",
    "\n",
    "data['Class'] = labels; pca_df2['Class'] = labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:53.482241Z",
     "iopub.status.busy": "2022-10-21T12:55:53.481799Z",
     "iopub.status.idle": "2022-10-21T12:55:53.705897Z",
     "shell.execute_reply": "2022-10-21T12:55:53.704348Z",
     "shell.execute_reply.started": "2022-10-21T12:55:53.482204Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "unique_labels = set(labels)\n",
    "colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))]\n",
    "for k, col in zip(unique_labels, colors):\n",
    "    if k == -1:\n",
    "        # Black used for noise.\n",
    "        col = [0, 0, 0, 1]\n",
    "    class_member_mask = labels == k\n",
    "\n",
    "    xy = m2[class_member_mask & core_samples_mask]\n",
    "    plt.plot(xy[:, 0], xy[:, 1], \"o\", markerfacecolor = tuple(col), markeredgecolor = \"k\", markersize = 14)\n",
    "\n",
    "    xy = m2[class_member_mask & ~core_samples_mask]\n",
    "    plt.plot(xy[:, 0], xy[:, 1], \"o\", markerfacecolor = tuple(col), markeredgecolor = \"k\", markersize = 6)\n",
    "\n",
    "plt.title(\"Estimated number of clusters: %d\" % n_clusters_)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- We again draw boxplots of **income** & **child_mort** w.r.t labelled clusters for identifying the assistance required by the nations!\n",
    "- We know that **low income and high child mortality** is a sign of an **economically backward nation**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:55:58.702366Z",
     "iopub.status.busy": "2022-10-21T12:55:58.701907Z",
     "iopub.status.idle": "2022-10-21T12:55:59.065962Z",
     "shell.execute_reply": "2022-10-21T12:55:59.064194Z",
     "shell.execute_reply.started": "2022-10-21T12:55:58.702324Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15,5))\n",
    "\n",
    "plt.subplot(1,2,1)\n",
    "sns.boxplot(x = 'Class', y = 'child_mort', data  = data, color = '#FF781F');\n",
    "plt.title('child_mort vs Class')\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.boxplot(x = 'Class', y = 'income', data  = data, color = '#FF781F');\n",
    "plt.title('income vs Class')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the above plot we can conclude :\n",
    "    - **-1 : Noise / Outliers**\n",
    "    - **0 : Help Needed**\n",
    "    - **1 : Might Need Help**\n",
    "    - **2 : No Help Needed**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:06.552184Z",
     "iopub.status.busy": "2022-10-21T12:56:06.551733Z",
     "iopub.status.idle": "2022-10-21T12:56:06.647952Z",
     "shell.execute_reply": "2022-10-21T12:56:06.646485Z",
     "shell.execute_reply.started": "2022-10-21T12:56:06.552149Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "pca_df2['Class'].loc[pca_df2['Class'] == -1] = 'Noise / Outliers'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 0] = 'Help Needed'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 1] = 'Might Need Help'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 2] ='No Help Needed'\n",
    "\n",
    "fig = px.choropleth(pca_df2[['Country','Class']],\n",
    "                    locationmode = 'country names',\n",
    "                    locations = 'Country',\n",
    "                    title = 'Needed Help Per Country (World)',\n",
    "                    color_discrete_sequence=[\"orange\", \"red\", \"green\",'black'],\n",
    "                    color = pca_df2['Class'],  \n",
    "                    color_discrete_map={'Noise / Outliers' : 'Black',\n",
    "                                        'Help Needed':'Red',\n",
    "                                        'Might Need Help':'Yellow',\n",
    "                                        'No Help Needed':'Green'})\n",
    "fig.update_geos(fitbounds = \"locations\", visible = True)\n",
    "fig.update_layout(legend_title_text = 'Labels',legend_title_side = 'top',title_pad_l = 260,title_y = 0.86)\n",
    "fig.show(engine = 'kaleido')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <center>Hierarchical Clustering<center>\n",
    "\n",
    "**Hierarchical Clustering** is a distanced based algorithm that is used for unsupervised learning problems. \n",
    "    \n",
    "- It develops the hierarchy of clusters in the form of a tree i.e known as the **dendrogram**. For this problem we are going to use **Agglomerative Clustering** which is a bottom-up approach that considers all the points as clusters and then merges them together based on their distances in the following ways :\n",
    "    - Initally all the points are considered as clusters.\n",
    "    - Then, clusters that are closer together they start merging as new cluster.\n",
    "    - This combined cluster then further gets compared with other clusters and the closest cluster gets merged.\n",
    "    - This process continues till a single large cluster is formed.\n",
    "- This process of forming clusters can then be viewed with a **dendrogram**. From it, we select the number of clusters by identifying the number of merges present at the penultimate stage. More is the length of the vertical lines, higher the distance between the clusters.\n",
    "- To select the number of clusters, we set a threshold value and count the number of vertical lines present above it. This number of vertical lines forms the number of clusters. Other methods like **Silhouette Score Method** and **Elbow method** can also be used.\n",
    "- For **Agglomerative Clustering**, it has 2 important hyperparameters :\n",
    "    - **linkage** : There are various connecting or linking methods for cluster i.e Single, Centroid, Average , etc.\n",
    "    - **affinity** : It is the distance formula that compares the distance before merging the clusters. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:08.693362Z",
     "iopub.status.busy": "2022-10-21T12:56:08.692892Z",
     "iopub.status.idle": "2022-10-21T12:56:08.699728Z",
     "shell.execute_reply": "2022-10-21T12:56:08.698174Z",
     "shell.execute_reply.started": "2022-10-21T12:56:08.693323Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from scipy.cluster.hierarchy import dendrogram, linkage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>Feature Combination : Health - Trade - Finance</center> "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:12.652413Z",
     "iopub.status.busy": "2022-10-21T12:56:12.651404Z",
     "iopub.status.idle": "2022-10-21T12:56:16.301610Z",
     "shell.execute_reply": "2022-10-21T12:56:16.300031Z",
     "shell.execute_reply.started": "2022-10-21T12:56:12.652345Z"
    },
    "scrolled": true,
    "trusted": true
   },
   "outputs": [],
   "source": [
    "linkage_data = linkage(m1, method = 'ward', metric = 'euclidean')\n",
    "dendrogram(linkage_data)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- In this case, we need to divide the countries into 3 categories. That is why we will select a 3 clusters directly. Dendrogram analysis for this dataset is kind of redundant. \n",
    "- Here, we can see that 1 **blue line** alongwith 2 **red lines** are the penultimate clusters that before connecting together.\n",
    "- It has 3 branches, thus indicating the **3 clusters** that it creates before merging into 1!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:16.304540Z",
     "iopub.status.busy": "2022-10-21T12:56:16.303754Z",
     "iopub.status.idle": "2022-10-21T12:56:16.313281Z",
     "shell.execute_reply": "2022-10-21T12:56:16.311968Z",
     "shell.execute_reply.started": "2022-10-21T12:56:16.304502Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from sklearn.cluster import AgglomerativeClustering\n",
    "hierarchical_cluster = AgglomerativeClustering(n_clusters = 3, affinity = 'euclidean', linkage = 'ward')\n",
    "labels = hierarchical_cluster.fit(m1)\n",
    "\n",
    "pred_agc = pd.Series(hierarchical_cluster.labels_)\n",
    "data['Class'] = pred_agc; df1['Class'] = pred_agc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:20.806238Z",
     "iopub.status.busy": "2022-10-21T12:56:20.805488Z",
     "iopub.status.idle": "2022-10-21T12:56:21.048069Z",
     "shell.execute_reply": "2022-10-21T12:56:21.046688Z",
     "shell.execute_reply.started": "2022-10-21T12:56:20.806202Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.figure()\n",
    "ax = Axes3D(fig)\n",
    "x = np.array(df1['Health'])\n",
    "y = np.array(df1['Trade'])\n",
    "z = np.array(df1['Finance'])\n",
    "ax.scatter(x,y,z,c = df1['Class'])\n",
    "plt.title('Health vs Trade vs Finance')\n",
    "ax.set_xlabel('Health')\n",
    "ax.set_ylabel('Trade')\n",
    "ax.set_zlabel('Finance')\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Now we have got the clusters but we don't know which value corresponds to what! \n",
    "- Hence, we draw a boxplots of **income** & **child_mort** w.r.t labelled clusters!\n",
    "- We know that **low income and high child mortality** is a sign of an **economically backward nation**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:23.624625Z",
     "iopub.status.busy": "2022-10-21T12:56:23.623706Z",
     "iopub.status.idle": "2022-10-21T12:56:23.974546Z",
     "shell.execute_reply": "2022-10-21T12:56:23.973138Z",
     "shell.execute_reply.started": "2022-10-21T12:56:23.624556Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15,5))\n",
    "\n",
    "plt.subplot(1,2,1)\n",
    "sns.boxplot(x = 'Class', y = 'child_mort', data  = data, color = '#FF781F');\n",
    "plt.title('child_mort vs Class')\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.boxplot(x = 'Class', y = 'income', data  = data, color = '#FF781F');\n",
    "plt.title('income vs Class')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the above plot we can conclude :\n",
    "    - **0 : No Help Needed**\n",
    "    - **1 : Help Needed**\n",
    "    - **2 : Might Need Help**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:33.635858Z",
     "iopub.status.busy": "2022-10-21T12:56:33.635302Z",
     "iopub.status.idle": "2022-10-21T12:56:33.730852Z",
     "shell.execute_reply": "2022-10-21T12:56:33.729325Z",
     "shell.execute_reply.started": "2022-10-21T12:56:33.635802Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "df1['Class'].loc[df1['Class'] == 0] = 'No Help Needed'\n",
    "df1['Class'].loc[df1['Class'] == 1] = 'Help Needed'\n",
    "df1['Class'].loc[df1['Class'] == 2] = 'Might Need Help'\n",
    "\n",
    "fig = px.choropleth(df1[['Country','Class']],\n",
    "                    locationmode = 'country names',\n",
    "                    locations = 'Country',\n",
    "                    title = 'Needed Help Per Country (World)',\n",
    "                    color = df1['Class'],  \n",
    "                    color_discrete_map = {'Help Needed' : 'Red',\n",
    "                                          'Might Need Help' : 'Yellow',\n",
    "                                          'No Help Needed' : 'Green'})\n",
    "fig.update_geos(fitbounds = \"locations\", visible = True)\n",
    "fig.update_layout(legend_title_text = 'Labels',legend_title_side = 'top',title_pad_l = 260,title_y = 0.86)\n",
    "fig.show(engine = 'kaleido')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <center>PCA Data</center>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:35.712882Z",
     "iopub.status.busy": "2022-10-21T12:56:35.712253Z",
     "iopub.status.idle": "2022-10-21T12:56:39.408234Z",
     "shell.execute_reply": "2022-10-21T12:56:39.407115Z",
     "shell.execute_reply.started": "2022-10-21T12:56:35.712847Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "linkage_data = linkage(m2, method = 'ward', metric = 'euclidean')\n",
    "dendrogram(linkage_data)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- In this case, we need to divide the countries into 3 categories. That is why we will select a 3 clusters directly. Dendrogram analysis for this dataset is kind of redundant.\n",
    "- Here, again, we can see that 1 **blue line** alongwith 2 **red lines** are the penultimate clusters formed before connecting together.\n",
    "- It has 3 branches, thus indicating the **3 clusters** that it creates before merging into 1!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:39.410484Z",
     "iopub.status.busy": "2022-10-21T12:56:39.410137Z",
     "iopub.status.idle": "2022-10-21T12:56:39.419420Z",
     "shell.execute_reply": "2022-10-21T12:56:39.418026Z",
     "shell.execute_reply.started": "2022-10-21T12:56:39.410453Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from sklearn.cluster import AgglomerativeClustering\n",
    "hierarchical_cluster = AgglomerativeClustering(n_clusters = 3, affinity = 'euclidean', linkage = 'ward')\n",
    "labels = hierarchical_cluster.fit(m2)\n",
    "\n",
    "pred_agc = pd.Series(hierarchical_cluster.labels_)\n",
    "data['Class'] = pred_agc; pca_df2['Class'] = pred_agc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:40.902703Z",
     "iopub.status.busy": "2022-10-21T12:56:40.902213Z",
     "iopub.status.idle": "2022-10-21T12:56:41.167187Z",
     "shell.execute_reply": "2022-10-21T12:56:41.165976Z",
     "shell.execute_reply.started": "2022-10-21T12:56:40.902664Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig = plt.figure()\n",
    "ax = Axes3D(fig)\n",
    "x = np.array(pca_df2[0])\n",
    "y = np.array(pca_df2[1])\n",
    "z = np.array(pca_df2[2])\n",
    "ax.scatter(x,y,z,c = pca_df2['Class'])\n",
    "plt.title('PCA Data')\n",
    "ax.set_xlabel('0th Component')\n",
    "ax.set_ylabel('1st Component')\n",
    "ax.set_zlabel('2nd Component')\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- We again draw boxplots of **income** & **child_mort** w.r.t labelled clusters!\n",
    "- We know that **low income and high child mortality** is a sign of an **economically backward nation**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:44.335145Z",
     "iopub.status.busy": "2022-10-21T12:56:44.334769Z",
     "iopub.status.idle": "2022-10-21T12:56:44.896058Z",
     "shell.execute_reply": "2022-10-21T12:56:44.894744Z",
     "shell.execute_reply.started": "2022-10-21T12:56:44.335113Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15,5))\n",
    "\n",
    "plt.subplot(1,2,1)\n",
    "sns.boxplot(x = 'Class', y = 'child_mort', data  = data, color = '#FF781F');\n",
    "plt.title('child_mort vs Class')\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "sns.boxplot(x = 'Class', y = 'income', data  = data, color = '#FF781F');\n",
    "plt.title('income vs Class')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- From the above plot we can conclude :\n",
    "    - **0 : Help Needed**\n",
    "    - **1 : Might Need Help**\n",
    "    - **2 : No Help Needed**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-10-21T12:56:55.608100Z",
     "iopub.status.busy": "2022-10-21T12:56:55.607689Z",
     "iopub.status.idle": "2022-10-21T12:56:55.690056Z",
     "shell.execute_reply": "2022-10-21T12:56:55.688342Z",
     "shell.execute_reply.started": "2022-10-21T12:56:55.608065Z"
    },
    "trusted": true
   },
   "outputs": [],
   "source": [
    "pca_df2['Class'].loc[pca_df2['Class'] == 0] = 'Help Needed'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 1] = 'Might Need Help'\n",
    "pca_df2['Class'].loc[pca_df2['Class'] == 2] = 'No Help Needed'\n",
    "\n",
    "fig = px.choropleth(pca_df2[['Country','Class']],\n",
    "                    locationmode = 'country names',\n",
    "                    locations = 'Country',\n",
    "                    title = 'Needed Help Per Country (World)',\n",
    "                    color = pca_df2['Class'],  \n",
    "                    color_discrete_map={'Help Needed':'Red',\n",
    "                                        'Might Need Help':'Yellow',\n",
    "                                        'No Help Needed':'Green'})\n",
    "fig.update_geos(fitbounds = \"locations\", visible = True)\n",
    "fig.update_layout(legend_title_text = 'Labels',legend_title_side = 'top',title_pad_l = 260,title_y = 0.86)\n",
    "fig.show(engine = 'kaleido')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Conclusion</div></center>\n",
    "\n",
    "- This is a great dataset that has been applied for a noble cause which highlights the scope of utilizing Data Science practices.\n",
    "\n",
    "\n",
    "- A model's performance is the reflection of the quality of the data feed to it. EDA section of this dataset provides a list of insights. Effect of normalization and standardization is massive on model performance.\n",
    "\n",
    "\n",
    "- Feature engineering is pivotal! For **feature combination & PCA data**, complexity of methods to achieve it is clearly visible. These processes highlight the various options open and thus requires us to be sensible in choosing the methods depending on the data and the problem statement.\n",
    "\n",
    "\n",
    "- **K-Means Clustering**, **Hierarchical Clustering** and **DBSCAN Clustering** are fundamentally different. They are based on different principles, thus displaying the difference in the model performances. Overall the model performances are not as great.    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### References :\n",
    "- https://brainly.in/question/6909751#:~:text=Answer%3A,and%20increase%20in%20population%20etc.\n",
    "- https://www.sefidian.com/2020/12/18/how-to-determine-epsilon-and-minpts-parameters-of-dbscan-clustering/\n",
    "- https://www.youtube.com/watch?v=7xHsRkOdVwo\n",
    "- https://sharkcoder.com/data-visualization/seaborn-boxplot\n",
    "- [For plotly world map, referred Kaggle Notebook | Username - IRON486](https://www.kaggle.com/code/die9origephit/country-data-clustering-k-means-and-visualization)\n",
    "- [Image Source](http://help-international.org/sites/default/files/images/CAM21488.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Please upvote if you like the work!</div><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Any sort of feedback is appreciated!</div><div style=\"font-family: Trebuchet MS; background-color: #FF781F; color: #2D2926; padding: 12px; line-height: 1;\">Thank You!</div></center>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
